﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using System.IO;
using System.Diagnostics;
using System.Threading.Tasks;
using System.Threading;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Media;
using System.Net;

namespace TriExporterNET
{
    public partial class frmMain : Form
    {
        public frmMain()
        {
            InitializeComponent();
        }

        void StuffFileEntry_Loading(object sender, EventArgs e)
        {
            BeginInvoke(new Action(() => progressBar.Value += 1));
        }
        
        private void tvMain_NodeMouseDoubleClick(object sender, TreeNodeMouseClickEventArgs e)
        {
            Stuff.StuffFileEntry sf = e.Node.Tag as Stuff.StuffFileEntry;
            if (sf != null)
            {

                switch (sf.Extension)
                {
                    case ".txt":
                    case ".fx":
                    case ".fxh":
                    case ".m3u":
                        using (var st = sf.GetStream())
                        using (var sr = new StreamReader(st))
                            textBox1.Text = sr.ReadToEnd();
                        textBox1.BringToFront();
                        break;
                    case ".black":
                        try
                        {
                            modelViewer.Model = new Engine.EVEMesh(modelViewer.GraphicsDevice, sf.FullName, list, sf.Extension == ".black");
                            modelViewer.BringToFront();
                        }
                        catch (Exception ex)
                        {
                            modelViewer.Model = null;
                            MessageBox.Show(ex.ToString());
                            if (hexBox1.ByteProvider != null)
                                ((Be.Windows.Forms.DynamicFileByteProvider)hexBox1.ByteProvider).Dispose();
                            hexBox1.ByteProvider = new Be.Windows.Forms.DynamicFileByteProvider(sf.GetStream());
                            hexBox1.BringToFront();
                        }
                        break;
                    case ".red":
                        try
                        {
                            modelViewer.Model = new Engine.EVEMesh(modelViewer.GraphicsDevice, sf.FullName, list, false);
                            modelViewer.BringToFront();
                        }
                        catch (Exception ex)
                        {
                            modelViewer.Model = null;
                            MessageBox.Show(ex.ToString());
                            using (var st = sf.GetStream())
                            using (var sr = new StreamReader(st))
                                textBox1.Text = sr.ReadToEnd();
                            textBox1.BringToFront();
                        }
                        break;
                    case ".wav":
                    case ".ogg":
                        FrameworkDispatcher.Update();
                        MediaPlayer.Play(Song.FromUri(sf.Name, new Uri(string.Format("{0}{1}?sf={2}", HTTPServer.Server.Adress, sf.FullName.Replace(' ', '+'), sf.StuffName))));
                        break;
                    default:
                        if (hexBox1.ByteProvider != null)
                            ((Be.Windows.Forms.DynamicFileByteProvider)hexBox1.ByteProvider).Dispose();
                        hexBox1.ByteProvider = new Be.Windows.Forms.DynamicFileByteProvider(sf.GetStream());
                        hexBox1.BringToFront();
                        break;
                }
            }
        }


        List<Stuff.StuffFileEntry> list;
        private void Form1_Load(object sender, EventArgs e)
        {
            var start = DateTime.Now;
            string path = @"c:\Program files\ccp\eve";
            try
            {
                path = Properties.Settings.Default.EVEPath;
            }
            catch { }
            var fileList = new DirectoryInfo(path).GetFiles("*.stuff").ToList();
            progressBar.Maximum = fileList.Count + 1;
            progressBar.Value = 0;
            labelStrip.Text = "Parsing stuff files...";
            Task.Factory.StartNew(() =>
                {

                    //Microsoft.Xna.Framework.Content.ContentManager mgr = new Microsoft.Xna.Framework.Content.ContentManager(modelViewer.Services, @"C:\Users\Selvin\Documents\Visual Studio 2010\Projects\TriExporterNET\content");
                    //modelViewer.Model = mgr.Load<Microsoft.Xna.Framework.Graphics.Model>("Model");
                });
            Task.Factory.StartNew<List<Stuff.StuffFileEntry>>(new Func<List<Stuff.StuffFileEntry>>(() =>
            {

                Stuff.StuffFileEntry.Loading += new EventHandler(StuffFileEntry_Loading);
                var List = Stuff.StuffFileEntry.LoadAll(fileList);
                try
                {
                    HTTPServer.Server.Setup(List);
                }
                catch { }
                Stuff.StuffFileEntry.Loading -= new EventHandler(StuffFileEntry_Loading);
                Invoke(new Action(() =>
                    {
                        labelStrip.Text = "Loading treeview...";
                        tvMain.BeginUpdate();
                        tvMain.Nodes.Clear();
                    }));
                list = List;
                return List;
            })).ContinueWith(task =>
            {
                Dictionary<string, int> lastdir = new Dictionary<string, int>();
                task.Result.ForEach(file =>
                {
                    TreeNodeCollection tns = tvMain.Nodes;
                    file.Path.SelectAllPaths().ToList().ForEach(x =>
                    {
                        var tmp = tns[x.Item1];
                        if (tmp == null)
                        {
                            if (lastdir.ContainsKey(x.Item3))
                            {
                                tmp = tns.Insert(lastdir[x.Item3], x.Item1, x.Item2);
                                lastdir[x.Item3] += 1;
                            }
                            else
                            {
                                tmp = tns.Insert(0, x.Item1, x.Item2);
                                lastdir[x.Item3] = 1;
                            }
                        }
                        tns = tmp.Nodes;
                    });
                    string key = file.Extension;
                    switch (file.Extension)
                    {
                        case ".mp3":
                        case ".ogg":
                        case ".m3u":
                        case ".wav":
                            key = "music";
                            break;
                        case ".css":
                        case ".fx":
                        case ".fxh":
                            key = ".txt";
                            break;
                        default:
                            if (!imageList.Images.ContainsKey(key))
                                key = "unk";
                            break;
                    }

                    TreeNode filenode = tns.Add(file.FullName, string.Format("{0} - {1:0.00}KB", file.Name, file.Length / 1024.0), key, key);
                    filenode.Tag = file;
                });
                tvMain.EndUpdate();
                progressBar.Visible = false;
                labelStrip.Text = string.Format("Done in {0}", DateTime.Now - start);
            }, CancellationToken.None, TaskContinuationOptions.OnlyOnRanToCompletion, TaskScheduler.FromCurrentSynchronizationContext());
        }

        private void modelViewer_Click(object sender, EventArgs e)
        {
            MessageBox.Show("");
        }

        private void frmMain_KeyDown(object sender, KeyEventArgs e)
        {
            modelViewer.KeyDown1(sender, e);
        }

        private void tvMain_NodeMouseClick(object sender, TreeNodeMouseClickEventArgs e)
        {
            if (e.Button == System.Windows.Forms.MouseButtons.Right)
            {
                var stufffile = e.Node.Tag as Stuff.StuffFileEntry;
                if (stufffile != null)
                { 
                    var dialog = new FolderBrowserDialog();
                    /* just debug stuff .... putting non parsable black files on my desktop
                    Task.Factory.StartNew(() =>
                        {
                            var start = DateTime.Now;
                            int counter = 0;
                            var aa = list.Where(x => x.Name.EndsWith(".black")).ToList();
                            List<Red.BlackObject> Ok = new List<Red.BlackObject>();
                            List<Stuff.StuffFileEntry> Bad = new List<Stuff.StuffFileEntry>();
                            foreach (var sf in aa)
                            {
                                counter++;
                                Invoke(new Action(() =>
                                {
                                    labelStrip.Text = string.Format("{0}/{1}", counter, aa.Count);
                                }));
                                
                                try
                                {
                                    Ok.Add(new Red.BlackObject(sf.GetStream()));
                                }
                                catch
                                {
                                    Bad.Add(sf);
                                    using (var fs = File.Open(Path.Combine(@"C:\Users\Selvin\Desktop\eve\bad", string.Format("{0}.black", counter)), FileMode.Create, FileAccess.Write))
                                        sf.GetStream().CopyTo(fs);
                                }
                            }
                            Invoke(new Action(() =>
                            {
                                labelStrip.Text += string.Format("Bad: c: {0}s: {1}", Bad.Count, Bad.Sum(x=>x.Length)); 
                            }));
                            counter = 0;

                            
                        });*/
                    if (dialog.ShowDialog() == System.Windows.Forms.DialogResult.OK)
                    {
                        using (var fs = File.Open(Path.Combine(dialog.SelectedPath, stufffile.Name), FileMode.Create, FileAccess.Write))
                            stufffile.GetStream().CopyTo(fs);
                    }
                }
            }
        }
    }

    public static class EC
    {

        public static IEnumerable<Tuple<string, string, string>> SelectAllPaths(this string path)
        {
            string[] pathparts = path.Split('\\');
            if (pathparts.Length != 0)
            {
                var lstnp = string.Empty;
                for (int i = 0; i < pathparts.Length; i++)
                {
                    string npath = string.Join("\\", pathparts, 0, i + 1);
                    if (npath != string.Empty)
                    {
                        var tmp = lstnp;
                        lstnp = npath;
                        yield return new Tuple<string, string, string>(npath, pathparts[i], tmp);
                    }
                }
            }
        }
    }
}
